package com.theaf.basemodule.service.impl;

import com.theaf.basemodule.common.api.MesTemplateService;;
import com.theaf.basemodule.common.api.OrganService;
import com.theaf.basemodule.common.api.UserService;
import com.theaf.basemodule.common.condition.MesTemplateCondition;
import com.theaf.basemodule.common.dto.mesTemplate.MesTemplateDTO;
import com.theaf.basemodule.common.dto.mesTemplate.NotifyScopeDTO;
import com.theaf.basemodule.common.dto.mesTemplate.TemplateWayDTO;
import com.theaf.basemodule.common.dto.organ.ContactDTO;
import com.theaf.basemodule.common.dto.user.UserDTO;
import com.theaf.basemodule.common.model.mesTemplate.*;
import com.theaf.basemodule.common.vo.mesTemplate.MesTemplateVo;
import com.theaf.basemodule.dao.PositionDAO;
import com.theaf.basemodule.dao.mestemplate.MesMessageDAO;
import com.theaf.basemodule.dao.mestemplate.MesTemplateDAO;
import com.theaf.basemodule.service.other.SiteMesService;
import com.theaf.basemodule.service.other.SmsService;
import com.theaf.basemodule.service.other.WeixinService;
import com.theaf.core.annotation.MqConfig;
import com.theaf.core.repo.specification.SqlBuilder;
import com.theaf.core.repo.specification.SqlOperator;
import com.theaf.core.repo.specification.SqlValue;
import com.theaf.core.rmq.MessageProcess;
import com.theaf.core.rmq.common.MqReturn;
import com.theaf.core.service.Message;
import com.theaf.core.utils.DateUtils;
import com.theaf.core.utils.DictionaryHelper;
import com.theaf.core.utils.SmExceptionHelper;
import com.theaf.core.utils.StringUtils;
import org.dozer.Mapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.transaction.Transactional;
import java.io.Serializable;
import java.util.*;

import static com.theaf.basemodule.common.model.mesTemplate.MesNotifyScope.*;

/**
 * @Author:songwenke
 * @Description:消息服务
 * @Date:create in 16:28 2018/2/11
 * @Modified By:
 **/
@Service
@MqConfig(topic="topic_mes")
public class MesTemplateServiceImpl implements MesTemplateService,MessageProcess<Message> {

    @Resource
    private MesTemplateDAO mesTemplateDAO;
    @Resource
    private MesMessageDAO mesMessageDAO;
    @Resource
    private PositionDAO positionDAO;
    @Resource
    private OrganService organService;
    @Resource
    private Mapper mapper;

    @Autowired
    private WeixinService weixinService;
    @Autowired
    private SiteMesService siteMesService;
    @Autowired
    private UserService userService;

    /**
     * 保存消息模版
     * @param vo
     */
    @Override
    public void save(MesTemplateVo vo) {
        MesTemplate mesTemplate = mesTemplateDAO.findByIdNewIfisNull(vo.getId());
        if (mesTemplateDAO.count(
                SqlBuilder.start("code",SqlValue.parse(vo.getCode())).
                        and("id", SqlOperator.OPER.NE,vo.getId()).gen())>0) {
                throw SmExceptionHelper.reqLogValidException("模版编码已存在！");
        }
        mapper.map(vo,mesTemplate);
        mesTemplate.getMesNotifyScopeList().clear();
        vo.getNotifyScopeVoList().forEach(n->{
            mesTemplate.getMesNotifyScopeList().add(mapper.map(n,MesNotifyScope.class));
        });
        mesTemplate.getMesTemplateWayList().clear();
        vo.getTemplateWayList().forEach(n->{
            mesTemplate.getMesTemplateWayList().add(mapper.map(n,MesTemplateWay.class));
        });
        mesTemplateDAO.save(mesTemplate);
    }

    /**
     * 删除消息模版
     * @param id
     */
    @Override
    public void delete(Long id) {
        if (id == null || null == mesTemplateDAO.findOne(id)) {
            throw SmExceptionHelper.reqArgValidException("模版id不存在！");
        }
        mesTemplateDAO.delete(id);
    }

    @Override
    public MesTemplateDTO find(Long id) {
        if (id == null || null == mesTemplateDAO.findOne(id)) {
            throw SmExceptionHelper.reqArgValidException("模版id不存在！");
        }
        MesTemplate mesTemplate = mesTemplateDAO.findOne(id);
        MesTemplateDTO mesTemplateDto = new MesTemplateDTO();
        mapper.map(mesTemplate, mesTemplateDto);
        mesTemplateDto.setNotifyScopeDtos(new ArrayList());
        mesTemplate.getMesNotifyScopeList().forEach(n->{
            NotifyScopeDTO notifyScopeDTO = mapper.map(n,NotifyScopeDTO.class);
            notifyScopeDTO.setContactName(DictionaryHelper.getChlidValue("contact_type",notifyScopeDTO.getContact()));
            if(notifyScopeDTO.getPosId()!=null) {
                notifyScopeDTO.setPosName(positionDAO.findOne(notifyScopeDTO.getPosId()).getName());
            }
            mesTemplateDto.getNotifyScopeDtos().add(notifyScopeDTO);
        });
        mesTemplateDto.setTemplateWayDtos(new ArrayList());
        mesTemplate.getMesTemplateWayList().forEach(n->{
            mesTemplateDto.getTemplateWayDtos().add(mapper.map(n,TemplateWayDTO.class));
        });
        return mesTemplateDto;
    }

    /**
     * 分页查询
     * @param condition 查询条件
     * @return
     */
    @Override
    public Page<MesTemplateDTO> query(MesTemplateCondition condition) {
        Page<MesTemplate> mesTemplatePage = mesTemplateDAO.findCustom(condition);
        return mesTemplatePage.map(a->mapper.map(mesTemplatePage, MesTemplateDTO.class));
    }

    /**
     * 消息队列接收器
     * @param message 消息体
     * @param excuteNumber 执行次数
     * @param id 消息标识
     * @return
     */
    @Override
    @Transactional(dontRollbackOn=RuntimeException.class)
    public MqReturn process(Message message, int excuteNumber, String id) {
        List<MesMessage> mesMessages = mesMessageDAO.findAll(SqlBuilder.start("mqId",SqlValue.parse(id)).gen());
        final boolean[] successed = {true};
        if(mesMessages==null||mesMessages.size()==0) {//第一次发送
            MesTemplate mesTemplate = null;
            if(StringUtils.isNotEmpty(message.getCode())) {
                mesTemplate = mesTemplateDAO.findByCode(message.getCode());
            }
            if(mesTemplate!=null) {//存在模板编码
                List<MesNotifyScope> mesNotifyScopes = mesTemplate.getMesNotifyScopeList();
                for (MesNotifyScope scope : mesNotifyScopes) {
                    switch (scope.getType()) {
                        case TYPE_ORGAN_CONTACT: {
                            List<ContactDTO> contactDTOS = null;
                            if(scope.getChilded()){
                                contactDTOS = organService.findAllChildContact(message.getOrganId()==null?scope.getOrgId():message.getOrganId(),
                                        StringUtils.isEmpty(message.getContact())?scope.getContact():message.getContact());
                            }else{
                                contactDTOS = organService.findContact(message.getOrganId()==null?scope.getOrgId():message.getOrganId(),
                                        StringUtils.isEmpty(message.getContact())?scope.getContact():message.getContact());
                            }
                            successed[0] &= sendContact(contactDTOS, mesTemplate, message, id);
                            break;
                        }
                        case TYPE_ORGAN_POS: {//岗位
                            successed[0] &= sendUser(userService.findByOrganAndPos(message.getOrganId() != null ? message.getOrganId() : scope.getOrgId(),
                                    scope.getChilded(), message.getPosId() != null ? message.getPosId() : scope.getPosId()), mesTemplate, message, id);
                            break;
                        }
                        case TYPE_ORGAN_RES: {//责任人
                            successed[0] &= sendUser(userService.findResByOrgan(message.getOrganId() != null ? message.getOrganId() : scope.getOrgId(),
                                    scope.getChilded()), mesTemplate, message, id);
                            break;
                        }
                        case TYPE_ORGAN_PON: {//开拓者
                            successed[0] &= sendUser(userService.findResByOrgan(message.getOrganId() != null ? message.getOrganId() : scope.getOrgId(),
                                    scope.getChilded()), mesTemplate, message, id);
                            break;
                        }
                        case TYPE_OTHER: {//其它，像手机、微信和单用户
                            successed[0] &= sendOther(StringUtils.isNotEmpty(message.getPhone()) ? message.getPhone() : scope.getPhone(),
                                    StringUtils.isNotEmpty(message.getWeixin()) ? message.getWeixin() : scope.getWeixin(),
                                    message.getUserId() != null ? message.getUserId() : scope.getUserId(), mesTemplate, message, id);
                            break;
                        }
                    }
                }
            }else{//无模板编码的
                message.setType(message.getType()==0?3:message.getType());//缺省发站内
                if(message.getOrganId()!=null&&StringUtils.isNotEmpty(message.getContact())){
                    List<ContactDTO> contactDTOS = organService.findContact(message.getOrganId(), message.getContact());
                    sendContact(contactDTOS, mesTemplate, message, id);
                }else if(message.getOrganId()!=null&&message.getPosId()!=null){
                    sendUser(userService.findByOrganAndPos(message.getOrganId(),
                            false, message.getPosId()), mesTemplate, message, id);
                }else{
                    sendOther(message.getPhone(), message.getWeixin(),
                            message.getUserId(), mesTemplate, message, id);
                }
            }
        }else{//出错之后的发送
            mesMessages.forEach(mes->{
                successed[0] &= sendFact(mes.getRecId(),mes.getRecId(),
                        mes.getMesWay()==3?Long.parseLong(mes.getRecId()):null,mes.getRecName(),mes);
                mesMessageDAO.save(mes);
            });
        }
        return MqReturn.success(null);
    }

    /**
     * 根据联系方式发送
     * @param contactDTOS 联系方式
     * @param mesTemplate
     * @param message
     * @param mqId
     * @return
     */
    private boolean sendContact(List<ContactDTO> contactDTOS,MesTemplate mesTemplate,Message message,String mqId){
        final boolean successed[] = {true};
        if(contactDTOS!=null&&contactDTOS.size()>0){
            List<MesTemplateWay> mesTemplateWays = new ArrayList();
            if(mesTemplate!=null){
                mesTemplateWays = mesTemplate.getMesTemplateWayList();
            }else{
                MesTemplateWay mesTemplateWay = new MesTemplateWay();
                mesTemplateWay.setType(message.getType());
                mesTemplateWay.setContent(message.getContent());
                mesTemplateWay.setResend(false);
                mesTemplateWays.add(mesTemplateWay);
            }
            for(MesTemplateWay way:mesTemplateWays) {
                contactDTOS.forEach(contact -> {
                    message.getParam().put("SYS_PARAM_USER",contact.getName());
                    MesMessage mesMessage = new MesMessage();
                    mesMessage.setCreateTime(new Date(System.currentTimeMillis()));
                    mesMessage.setIntro(way.getIntro());
                    mesMessage.setMesType(mesTemplate!=null?mesTemplate.getType():1);
                    mesMessage.setMqId(mqId);
                    mesMessage.setMesWay(way.getType());
                    mesMessage.setSender(message.getSender());
                    mesMessage.setTwId(way.getId());
                    mesMessage.setTitle(way.getTitle());
                    mesMessage.setContent(contentSetPara(way.getContent(),message.getParam()));
                    mesMessage.setMesEvents(new ArrayList());
                    successed[0] &= sendFact(contact.getPhone(),contact.getWeixin(),null,null,mesMessage);
                    mesMessageDAO.save(mesMessage);
                });
            }
        }
        return successed[0];
    }

    /**
     * 根据用户信息发送消息
     * @param users
     * @param mesTemplate
     * @param message
     * @param mqId
     * @return
     */
    private boolean sendUser(List<UserDTO> users, MesTemplate mesTemplate, Message message, String mqId){
         boolean successed = true;
        for(UserDTO user:users) {
            message.getParam().put("SYS_PARAM_USER",user.getCname());
            List<MesTemplateWay> mesTemplateWays = new ArrayList();
            if(mesTemplate!=null){
                mesTemplateWays = mesTemplate.getMesTemplateWayList();
            }else{
                MesTemplateWay mesTemplateWay = new MesTemplateWay();
                mesTemplateWay.setType(message.getType());
                mesTemplateWay.setContent(message.getContent());
                mesTemplateWay.setResend(false);
                mesTemplateWays.add(mesTemplateWay);
            }
            for(MesTemplateWay way:mesTemplateWays) {
                MesMessage mesMessage = new MesMessage();
                mesMessage.setCreateTime(new Date(System.currentTimeMillis()));
                mesMessage.setIntro(way.getIntro());
                mesMessage.setMesType(mesTemplate!=null?mesTemplate.getType():1);
                mesMessage.setMqId(mqId);
                mesMessage.setMesWay(way.getType());
                mesMessage.setSender(message.getSender());
                mesMessage.setTwId(way.getId());
                mesMessage.setTitle(way.getTitle());
                mesMessage.setContent(contentSetPara(way.getContent(),message.getParam()));
                mesMessage.setMesEvents(new ArrayList());
                successed &= sendFact(user.getMobile(),user.getWxId(),user.getId(),user.getCname(),mesMessage);
                mesMessageDAO.save(mesMessage);
            }
        }
        return successed;
    }

    /**
     * 根据手机微信用户发送消息
     * @param phone
     * @param weixin
     * @param userId
     * @param mesTemplate
     * @param message
     * @param mqId
     * @return
     */
    private boolean sendOther(String phone,String weixin,Long userId, MesTemplate mesTemplate, Message message, String mqId){
        boolean successed = true;
        List<MesTemplateWay> mesTemplateWays = new ArrayList();
        message.getParam().put("SYS_PARAM_USER",message.getReceiver());
        if(userId!=null&&message.getReceiver()==null){
            UserDTO userDTO = userService.findById(userId);
            if(userDTO!=null) {
                message.getParam().put("SYS_PARAM_USER", userDTO.getCname());
            }
        }
        if(mesTemplate!=null){
            mesTemplateWays = mesTemplate.getMesTemplateWayList();
        }else{
            MesTemplateWay mesTemplateWay = new MesTemplateWay();
            mesTemplateWay.setType(message.getType());
            mesTemplateWay.setContent(message.getContent());
            mesTemplateWay.setResend(false);
            mesTemplateWays.add(mesTemplateWay);
        }
        for(MesTemplateWay way:mesTemplateWays) {
            MesMessage mesMessage = new MesMessage();
            mesMessage.setCreateTime(new Date(System.currentTimeMillis()));
            mesMessage.setIntro(way.getIntro());
            mesMessage.setMesType(mesTemplate!=null?mesTemplate.getType():1);
            mesMessage.setMqId(mqId);
            mesMessage.setMesWay(way.getType());
            mesMessage.setSender(message.getSender());
            mesMessage.setTwId(way.getId());
            mesMessage.setTitle(way.getTitle());
            mesMessage.setContent(contentSetPara(way.getContent(),message.getParam()));
            mesMessage.setMesEvents(new ArrayList());
            successed &= sendFact(phone,weixin,userId,null,mesMessage);
            mesMessageDAO.save(mesMessage);
        }
        return successed;
    }

    /**
     * 消息实际发送方法
     * @param phone
     * @param weixin
     * @param userId
     * @param userName
     * @param mesMessage
     * @return
     */
    private boolean sendFact(String phone,String weixin,Long userId,String userName,MesMessage mesMessage){
        boolean ok = true;
        if(mesMessage.getMesWay()==1){//短信
            try {
                if(StringUtils.isNotEmpty(phone)) {
                    mesMessage.setRecId(phone);
                    mesMessage.setRecName(phone);
                    SmsService.sendSms(phone, mesMessage.getContent());
                }else if(userId!=null) {
                    UserDTO userDTO = userService.findById(userId);
                    if(userDTO!=null&&StringUtils.isNotEmpty(userDTO.getMobile())) {
                        SmsService.sendSms(userDTO.getMobile(), mesMessage.getContent());
                        mesMessage.setRecId(userDTO.getMobile());
                        mesMessage.setRecName(userDTO.getMobile());
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
                ok = false;
                mesMessage.getMesEvents().add(new MesEvent(2,e.getMessage(),new Date(System.currentTimeMillis())));
            }
        }else if(mesMessage.getMesWay()==2){//微信
            try {
                if(StringUtils.isNotEmpty(weixin)) {
                    mesMessage.setRecId(weixin);
                    mesMessage.setRecName(weixin);
                    if(weixin.startsWith("party:")){
                        weixinService.sendMessage(null, weixin.substring(6), null, mesMessage.getContent(), "1");
                    }else if(weixin.startsWith("tag:")){
                        weixinService.sendMessage(null, null, weixin.substring(4), mesMessage.getContent(), "1");
                    }else {
                        weixinService.sendMessage(weixin, null, null, mesMessage.getContent(), "1");
                    }
                }else if(userId!=null) {
                    UserDTO userDTO = userService.findById(userId);
                    mesMessage.setRecId(userId+"");
                    if(userDTO!=null&&StringUtils.isNotEmpty(userDTO.getWxId())) {
                        mesMessage.setRecName(userDTO.getCname());
                        weixinService.sendMessage(userDTO.getWxId(), null, null, mesMessage.getContent(), "1");
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
                ok = false;
                mesMessage.getMesEvents().add(new MesEvent(2,e.getMessage(),new Date(System.currentTimeMillis())));
            }
        }else{//站内
            try {
                if(userId!=null) {
                    mesMessage.setRecId(userId+"");
                    if(StringUtils.isEmpty(userName)){
                        UserDTO userDTO = userService.findById(userId);
                        userName = userDTO!=null?userDTO.getCname():"无名氏";
                    }
                    mesMessage.setRecName(userName);
                    siteMesService.sendMsg(userId, mesMessage.getRecName(), mesMessage.getContent());
                }
            }catch (Exception e) {
                e.printStackTrace();
                ok = false;
                mesMessage.getMesEvents().add(new MesEvent(2,e.getMessage(),new Date(System.currentTimeMillis())));
            }
        }
        if(ok){
            mesMessage.getMesEvents().add(new MesEvent(1,null,new Date(System.currentTimeMillis())));
        }
        return ok;
    }

    private String contentSetPara(String content,Map<String,Serializable> param){
        if(param!=null) {
            for (String key : param.keySet()) {
                content = content.replaceAll("\\$\\{" + key + "\\}", param.get(key) + "");
            }
        }
        content = content.replaceAll("\\$\\{SYS_PARAM_DATE\\}", DateUtils.convertDateToStr(new Date(System.currentTimeMillis()),"yyyy年MM月dd日"));
        return content;
    }
}